home *** CD-ROM | disk | FTP | other *** search
- /* Generic stream implementation -- header file.
- Copyright (C) 1995 Amdahl Corporation.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- /* Written by Ben Wing. */
-
- DECLARE_LRECORD (lstream, struct lstream);
- #define XLSTREAM(x) XRECORD (x, lstream, struct lstream)
- #define XSETLSTREAM(x, p) XSETRECORD (x, p, lstream)
- #define LSTREAMP(x) RECORDP (x, lstream)
- #define CHECK_LSTREAM(x, i) CHECK_RECORD (x, lstream)
-
- extern Lisp_Object Fstreamp (Lisp_Object obj);
-
- #ifndef EOF
- #define EOF (-1)
- #endif
-
- typedef enum lstream_buffering
- {
- /* No buffering. */
- LSTREAM_UNBUFFERED,
- /* Buffer until a '\n' character is reached. */
- LSTREAM_LINE_BUFFERED,
- /* Buffer in standard-size (i.e. 512-byte) blocks. */
- LSTREAM_BLOCK_BUFFERED,
- /* Buffer in blocks of a specified size. */
- LSTREAM_BLOCKN_BUFFERED,
- /* Buffer until the stream is closed (only applies to write-only
- streams). Only one call to the stream writer will be made,
- and that is when the stream is closed. */
- LSTREAM_UNLIMITED
- } Lstream_buffering;
-
- /* Methods defining how this stream works. Some may be undefined. */
-
- typedef struct lstream_implementation
- {
- char *name;
- /* Read some data from the stream's end and store it into DATA, which
- can hold SIZE bytes. Return the number of bytes read. 0 means
- EOF reached. This function can be NULL if the stream is output-
- only. */
- int (*reader) (Lstream *stream, unsigned char *data, int size);
- /* Send some data to the stream's end. Data to be sent is in
- DATA and is SIZE bytes. Return the number of bytes sent. 0
- means cannot store any more data (e.g. fixed block of memory),
- and the data will be discarded. If fewer bytes are sent than
- provided, the remaining bytes will be sent the next time around.
- This function can be NULL if the stream is input-only. */
- int (*writer) (Lstream *stream, CONST unsigned char *data, int size);
- /* Rewind the stream. If this is NULL, the stream is not seekable. */
- int (*rewinder) (Lstream *stream);
- /* Perform any additional operations necessary to close this
- stream down. May be NULL. This function is called when
- Lstream_close() is called or when the stream is garbage-
- collected. When this function is called, all pending data
- in the stream will already have been written out. */
- int (*closer) (Lstream *stream);
- /* Mark this object for garbage collection. Same semantics as
- a standard Lisp_Object marker. This function can be NULL. */
- Lisp_Object (*marker) (Lisp_Object lstream, void (*markfun) (Lisp_Object));
- int size; /* Number of additional bytes to be allocated with this
- stream. Access this data using Lstream_data(). */
- } Lstream_implementation;
-
- #define DEFINE_LSTREAM_IMPLEMENTATION(name,c_name,richman,poorman,beggarman,thief,and_somebody_else,size) \
- CONST_IF_NOT_DEBUG Lstream_implementation c_name[1] = \
- { { (name), (richman), (poorman), (beggarman), (thief), \
- (and_somebody_else), (size) } }
-
- struct lstream
- {
- struct lcrecord_header header;
- CONST Lstream_implementation *imp; /* methods for this stream */
- Lstream_buffering buffering; /* type of buffering in use */
- int buffering_size; /* number of bytes buffered */
-
- unsigned char *in_buffer; /* holds characters read from stream end */
- int in_buffer_size; /* allocated size of buffer */
- int in_buffer_current; /* number of characters in buffer */
- int in_buffer_ind; /* pointer to next character to take from buffer */
-
- unsigned char *out_buffer; /* holds characters to write to stream end */
- int out_buffer_size; /* allocated size of buffer */
- int out_buffer_ind; /* pointer to next buffer spot to write a character */
-
- unsigned char *unget_buffer; /* holds characters pushed back onto input */
- int unget_buffer_size; /* allocated size of buffer */
- int unget_buffer_start; /* read characters from here */
- int unget_buffer_end; /* write characters to here */
-
- int byte_count;
- long is_open; /* Align pointer for 64 bit machines (kny) */
- char data[1];
- };
-
- extern Lstream *Lstream_new (CONST Lstream_implementation *imp);
- extern void Lstream_reopen (Lstream *lstr);
- extern void Lstream_set_buffering (Lstream *lstr, Lstream_buffering buffering,
- int buffering_size);
- extern int Lstream_flush (Lstream *lstr);
- extern int Lstream_flush_out (Lstream *lstr);
- extern int Lstream_fputc (Lstream *stream, int c);
- extern int Lstream_fgetc (Lstream *stream);
- extern void Lstream_fungetc (Lstream *stream, int c);
- extern int Lstream_read (Lstream *stream, void *data, int size);
- extern int Lstream_write (Lstream *stream, CONST void *data, int size);
- extern void Lstream_unread (Lstream *stream, void *data, int size);
- extern int Lstream_rewind (Lstream *stream);
- extern int Lstream_close (Lstream *stream);
-
- /* Call the function equivalent if the out buffer is full. Otherwise,
- add to the end of the out buffer and, if line buffering is called for
- and the character marks the end of a line, write out the buffer. */
-
- #define Lstream_putc(stream, c) \
- ((stream)->out_buffer_ind >= (stream)->out_buffer_size ? \
- Lstream_fputc (stream, c) : \
- ((stream)->out_buffer[(stream)->out_buffer_ind++] = \
- (unsigned char) (c), \
- (stream)->byte_count++, \
- (stream)->buffering == LSTREAM_LINE_BUFFERED && \
- (stream)->out_buffer[(stream)->out_buffer_ind - 1] == '\n' ? \
- Lstream_flush_out (stream) : 0))
-
- /* Retrieve from unget buffer if there are any characters there;
- else retrieve from in buffer if there's anything there;
- else call the function equivalent */
- #define Lstream_getc(stream) \
- ((stream)->unget_buffer_start < (stream)->unget_buffer_end ? \
- ((stream)->byte_count++, \
- (stream)->unget_buffer[(stream)->unget_buffer_start++]) : \
- (stream)->in_buffer_ind < (stream)->in_buffer_current ? \
- ((stream)->byte_count++, \
- (stream)->in_buffer[(stream)->in_buffer_ind++]) : \
- Lstream_fgetc (stream))
-
- /* Add to the end if it won't overflow buffer; otherwise call the
- function equivalent */
- #define Lstream_ungetc(stream, c) \
- ((stream)->unget_buffer_end >= (stream)->unget_buffer_size ? \
- Lstream_fungetc (stream, c) : \
- (void) ((stream)->byte_count--, \
- ((stream)->unget_buffer[(stream)->unget_buffer_end++] = \
- (unsigned char) (c))))
-
- #define Lstream_data(stream) ((void *) ((stream)->data))
- #define Lstream_byte_count(stream) ((stream)->byte_count)
-
-
-
- /**************** stream implementations ****************/
-
- #define LSTR_CLOSING 1
- #define LSTR_ALLOW_QUIT 2
- extern Lisp_Object make_stdio_stream (FILE *stream, int flags);
- extern Lisp_Object make_filedesc_stream (int filedesc, int flags);
- extern void filedesc_stream_set_pty_flushing (Lstream *stream,
- int pty_max_bytes,
- Bufbyte eof_char);
- extern Lisp_Object make_lisp_string_stream (Lisp_Object string,
- Bytecount offset,
- Bytecount len);
- extern Lisp_Object make_fixed_buffer_stream (unsigned char *buf,
- int size);
- extern unsigned char *fixed_buffer_stream_ptr (Lstream *stream);
- extern Lisp_Object make_resizing_buffer_stream (void);
- extern unsigned char *resizing_buffer_stream_ptr (Lstream *stream);
- #define LSTR_SELECTIVE 1
- #define LSTR_IGNORE_ACCESSIBLE 2
- extern Lisp_Object make_lisp_buffer_stream (struct buffer *buf, Bufpos pos,
- Bufpos length, int flags);
-